#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <mysql/mysql.h>
#include <ctype.h>

#include "../inc/tcp.h"
#include "../inc/register.h"
#include "../inc/cJSON.h"

static int validate_password(const char *password);

// 处理注册指令
void handle_register_cmd(client_info_p client, cJSON *root, cJSON *response)
{
    const char *userid = cJSON_GetStringValue(cJSON_GetObjectItem(root, "userid"));
    const char *password = cJSON_GetStringValue(cJSON_GetObjectItem(root, "password"));

    // 检查账号密码是否为空
    if (userid == NULL || password == NULL || *userid == '\0' || *password == '\0')
    {
        cJSON_AddNumberToObject(response, "code", REG_ERROR_EMPTY_INPUT);
        cJSON_AddStringToObject(response, "message", "账号和密码不能为空");
        return;
    }

    register_code_t result = user_register(client->db_conn, userid, password);
    const char *message = "";

    switch (result)
    {
    case REG_SUCCESS:
        message = "注册成功!";
        break;
    case REG_ERROR_USER_EXISTS:
        message = "用户名已存在";
        break;
    case REG_ERROR_DB:
        message = "数据库错误";
        break;
    case REG_ERROR_USERID_LONG:
        message = "账号长度超出限制";
        break;
    case REG_ERROR_UNKNOWN:
        message = "未知错误";
        break;
    case REG_ERROR_EMPTY_INPUT:
        message = "账号和密码不能为空";
        break;
    case REG_ERROR_PASSWORD_FORMAT:
        message = "密码至少6位,且需包含字母和数字!";
        break;
    default:
        message = "未定义的错误码";
        break;
    }

    cJSON_AddNumberToObject(response, "code", result);
    cJSON_AddStringToObject(response, "message", message);
}

/**
 * 注册功能：检查用户名是否存在+账号长度限制+密码格式验证，不存在则插入数据库
 * @return 0=成功, 1=用户名已存在, 2=数据库错误, 3=账号长度超出限制, 4=账号或密码为空, 5=密码格式不正确
 */
int user_register(MYSQL *db_conn, const char *userid, const char *password)
{
    char sql[512] = {0};
    MYSQL_RES *result = NULL;

    // 检查账号和密码是否为空
    if (userid == NULL || *userid == '\0' || password == NULL || *password == '\0')
    {
        printf("[REG] 错误：账号或密码不能为空！\n");
        return 4;
    }

    // 检查账号长度
    if (strlen(userid) > (USERID_LEN - 1))
    {
        printf("[REG] 错误：账号长度超出限制！最大支持 %d 个字符（当前 %zu 个）\n",
               USERID_LEN - 1, strlen(userid));
        return 3;
    }

    // 验证密码格式
    if (validate_password(password) != 0)
    {
        printf("[REG] 错误：密码格式不正确！必须包含字母和数字，且长度大于6位\n");
        return 5;
    }

    // 检查账号是否已存在
    snprintf(sql, sizeof(sql),
             "SELECT userid FROM user WHERE userid = '%s' LIMIT 1", userid);
    if (mysql_query(db_conn, sql) != 0)
    {
        printf("[REG] 查询账号是否存在失败: %s\n", mysql_error(db_conn));
        return 2;
    }

    result = mysql_store_result(db_conn);
    if (result == NULL)
    {
        printf("[REG] 获取查询结果失败: %s\n", mysql_error(db_conn));
        return 2;
    }

    // 用户名已存在
    if (mysql_num_rows(result) > 0)
    {
        mysql_free_result(result);
        printf("[REG] 错误：账号 %s 已存在！\n", userid);
        return 1;
    }
    mysql_free_result(result);

    // 插入新用户
    snprintf(sql, sizeof(sql),
             "INSERT INTO user (userid, passwd, name) VALUES ('%s', '%s', '%s')",
             userid, password, userid);
    if (mysql_query(db_conn, sql) != 0)
    {
        printf("[REG] 插入新用户失败: %s\n", mysql_error(db_conn));
        return 2;
    }

    printf("[REG] 成功：账号 %s 注册完成！\n", userid);
    return 0;
}

/**
 * 验证密码格式 要求：至少包含一个字母和一个数字，且长度大于6位
 * @return 0=格式正确, 1=格式不正确
 */
static int validate_password(const char *password)
{
    int has_letter = 0;
    int has_digit = 0;
    size_t len;

    // 检查密码是否为空或长度不足
    if (password == NULL || *password == '\0' || (len = strlen(password)) < 6)
    {
        return 1;
    }

    // 检查是否包含字母和数字
    for (size_t i = 0; i < len; i++)
    {
        if (isalpha((unsigned char)password[i]))
        {
            has_letter = 1;
        }
        else if (isdigit((unsigned char)password[i]))
        {
            has_digit = 1;
        }
    }

    // 必须同时包含字母和数字
    if (!has_letter || !has_digit)
    {
        return 1;
    }

    return 0; // 格式正确
}